package com.neulogistics.contrib.transfercenter.api.application.integrationevent.handler;

import com.blackto.lib.eventbus.abstraction.IIntegrationEventHandler;
import com.neulogistics.contrib.transfercenter.api.application.integrationevent.ITransferCenterIntegrationEventService;
import com.neulogistics.contrib.transfercenter.api.application.integrationevent.publish.TaskOrderCreatedIntegrationEvent;
import com.neulogistics.contrib.transfercenter.api.application.integrationevent.subscribe.InventoryCheckedIntegrationEvent;
import com.neulogistics.contrib.transfercenter.api.application.rpc.ITransferCenterRPC;
import com.neulogistics.contrib.transfercenter.api.application.rpc.dto.CreateTaskOrderDTO;
import com.neulogistics.contrib.transfercenter.api.service.ThreadLocalService;
import com.neulogistics.contrib.transfercenter.domain.model.aggregate.TransferOrder;
import com.neulogistics.contrib.transfercenter.domain.model.enumeration.TransferOrderStatus;
import com.neulogistics.contrib.transfercenter.domain.repository.ITransferOrderRepository;
import com.neulogistics.infrastructure.cache.idservice.RedisIdUtil;
import com.neulogistics.infrastructure.common.annotation.ProduceEvent;
import com.neulogistics.infrastructure.integrationeventlog.model.IntegrationEventConstant;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;

@Component
public class InventoryCheckedIntegrationEventHandler implements IIntegrationEventHandler<InventoryCheckedIntegrationEvent> {
    @Resource
    ITransferOrderRepository transferOrderRepository;

    @Resource
    ITransferCenterRPC transferCenterRPC;

    @Resource
    ITransferCenterIntegrationEventService transferCenterIntegrationEventService;

    @Resource
    RedisIdUtil redisIdUtil;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    @ProduceEvent
    public CompletableFuture<Void> handle(InventoryCheckedIntegrationEvent event) {
        // 查询对应调拨单
        TransferOrder transferOrder = transferOrderRepository.findById(event.transferOrderId);
        // 缺货，调拨单挂起
        if(!event.isAdequate){
            transferOrder.setTransferStatus(TransferOrderStatus.Suspend);
            transferOrderRepository.save(transferOrder);
            return CompletableFuture.completedFuture(null);
        }

        // 不缺货，修改状态，生成任务单
        Integer subWarehouseId = event.subWarehouseId;
        Long orderId = event.orderId;

        CreateTaskOrderDTO createTaskOrderDTO = new CreateTaskOrderDTO(subWarehouseId, orderId, null);
        Long taskId = transferCenterRPC.createTaskOrder(createTaskOrderDTO);

        // 开启事务
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                // 修改状态为已调度
                transferOrder.setTransferStatus(TransferOrderStatus.Scheduled);
                transferOrder.setTaskId(taskId);
                transferOrderRepository.save(transferOrder);

                // 生成任务单生成事件，库房为出入库单设置任务单id
                Long eventId = redisIdUtil.nextId(IntegrationEventConstant.Integration_Event_Id_Key);
                TaskOrderCreatedIntegrationEvent taskOrderCreatedIntegrationEvent = new TaskOrderCreatedIntegrationEvent(eventId);
                taskOrderCreatedIntegrationEvent.setTaskId(taskId);
                taskOrderCreatedIntegrationEvent.setTransferOrderId(transferOrder.getTransferOrderId());

                // 获取当前事务id，并保存该集成事件
                Long transactionId = ThreadLocalService.transactionId.get();
                transferCenterIntegrationEventService.addAndSaveEvent(taskOrderCreatedIntegrationEvent, transactionId);
            } catch (Exception e){
                // 触发回滚
                throw new RuntimeException(e.getMessage());
            }
            }
        });
        return CompletableFuture.completedFuture(null);
    }
}
